package task

import (
	"fmt"
	"time"
)

// TaskHandler 任务控制器
type TaskHandler func() error

// TaskState 任务状态
type TaskState = int32

const (
	TaskStatePending  TaskState = iota // 任务状态: 待执行
	TaskStateRunning                   // 任务状态: 正在执行中
	TaskStateTimeout                   // 任务状态: 执行超时
	TaskStateFailed                    // 任务状态: 执行失败
	TaskStateRemoved                   // 任务状态: 已删除
	TaskStateFinished                  // 任务状态: 已完成
)

func TaskStateString(s TaskState) string {
	switch s {
	case TaskStatePending:
		return "Pending"
	case TaskStateRunning:
		return "Running"
	case TaskStateTimeout:
		return "Timeout"
	case TaskStateFailed:
		return "Failed"
	case TaskStateRemoved:
		return "Removed"
	case TaskStateFinished:
		return "Finished"
	}
	return "Unknown"
}

// Task 定时任务信息(含运行调度状态信息)
type Task struct {
	key       string
	handler   TaskHandler    // 任务执行回调函数
	isOnce    bool           // 是否为一次性任务
	isBuffer  bool           // 是否为一次性任务(缓冲模式),任务首次添加后/运行前将会忽略相同Key任务的添加操作
	runMax    int32          // 任务最多运行次数(周期任务有效)
	runCount  int32          // 任务已运行次数
	timeout   time.Duration  // 任务执行超时时间(未定义时默认为60秒)
	executeAt time.Time      // 任务执行计划时间
	interval  *taskInterval  // 任务执行的周期(周期任务有效)
	state     TaskState      // 任务状态
	scheduled *taskScheduled // 任务所在分片指针(TaskScheduled)
	heapIndex int            // 任务在队列中taskHeap堆中的索引位置
	pc        uintptr        // 创建任务的调用栈入口PC
}

// TaskInfo 定时任务基本信息(含运行状态信息)
type TaskInfo struct {
	Key           string
	IsOnce        bool          // 是否为一次性任务
	IsBuffer      bool          // 是否为一次性任务(缓冲模式),任务首次添加后/运行前将会忽略相同Key任务的添加操作
	RunMax        int32         // 任务最多运行次数(周期任务有效)
	RunCount      int32         // 任务已运行次数
	Timeout       time.Duration // 任务执行超时时间(未定义时默认为60秒)
	LastState     TaskState     // 任务最近一次状态结果状态
	LastRunAt     time.Time     // 任务最近一次运行时间
	LastConsuming time.Duration // 任务最近一次运行耗时
	LastError     error         // 任务最近一次运行错误
}

func (s TaskInfo) String() string {
	return fmt.Sprintf("{Key: %v, IsOnce: %v, IsBuffer: %v, RunMax: %v, RunCount: %v, Timeout: %v, LastState: %s, LastRunAt: %s, LastConsuming: %v, LastError: %v}",
		s.Key, s.IsOnce, s.IsBuffer, s.RunMax, s.RunCount, s.Timeout, TaskStateString(s.LastState), s.LastRunAt.Format(time.RFC3339Nano), s.LastConsuming, s.LastError)
}
